package com.dxp.plugins;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.apache.api.vo.ParamsVo;
import com.apache.api.vo.ResultEntity;
import com.apache.cache.util.Validator;
import com.apache.ius.common.CommonUtils;
import com.apache.ius.plugin.CustomMethodPlugin;
import com.apache.ius.plugin.IusPluginUtil;
import com.apache.tools.DataMap;
import com.apache.tools.DateUtils;
import com.apache.tools.StrUtil;
import com.dxp.utils.HttpService;
import com.netflix.appinfo.InstanceInfo;
import com.netflix.discovery.DiscoveryManager;
import com.netflix.discovery.shared.Application;
import org.apache.log4j.Logger;

import java.util.*;

/**
 * @description: 数据统计插件
 * @date: Created in 2020/10/28
 */
public class DataStatisticsPluginImpl implements CustomMethodPlugin {
    private Logger log = Logger.getLogger(getClass());
    @Override
    public Object beforeInvoke(Map<String, Object> paramMap) {
        log.info("数据统计插件---start->> ");
        String statType = StrUtil.doNull(String.valueOf(paramMap.get("statType")),"1");//统计类型
        if(StrUtil.isNull(statType)){
            paramMap.put(CustomMethodPlugin.resultMark, "缺少请求参数");
        }
        //List listData = new ArrayList();
        switch (statType){
            case "1":
                log.info(statType+".统计查询-系统与接口树形关系！");
                List listData = getStatistics1();
                paramMap.put(CustomMethodPlugin.resultMark, "操作成功");
                paramMap.put(CustomMethodPlugin.pluginInnerReturn, listData);
                break;
            case "2":
                log.info(statType+".统计查询-统计接口请求成功和失败！");
                getStatistics2(paramMap);
                break;
            case "3":
                log.info(statType+".统计查询-请求次数折线图！");
                getStatistics3(paramMap);
                break;
            case "4":
                log.info(statType+".统计查询-统计接口调用次数top10榜！");
                getStatistics4(paramMap);
                break;
            case "5":
                log.info(statType+".统计查询-统计服务使用方（接口被谁使用了）！");
                getStatistics5(paramMap);
                break;
            case "6"://接口使用系统列表
                String sql ="select sys_ename,sys_cname,user_owner as owner_company from dx_sys_reg s , (select apply_sys_ename from dx_sys_int_relation group by apply_sys_ename) n where s.sys_ename = n.apply_sys_ename";
                List list = (List)IusPluginUtil.getInstance().select(sql,0,0);
                paramMap.put(CustomMethodPlugin.resultMark, "操作成功");
                paramMap.put(CustomMethodPlugin.pluginInnerReturn, list);
                break;
            default:
                paramMap.put(CustomMethodPlugin.resultMark, "缺少请求参数");
        }
//        Map<String, Object> result = new HashMap<String, Object>();
//        result.put(CustomMethodPlugin.resultMark, "操作成功");
//        result.put(CustomMethodPlugin.pluginInnerReturn, listData);
        return null;
    }

    private List getStatistics1(){

        List<DataMap> resList = new ArrayList<>();
        Map<String,Object> whereMap = new HashMap<>();
        whereMap.put("orderBy","dxSysReg.sys_ename");
//        whereMap.put("dxSysReg.wi_sysEname","MES,ERP,hgtgcssystem,testxitongwaibutwo");
        ResultEntity resultEntity1 = IusPluginUtil.getInstance().select("list", "s_dxSysReg", whereMap);
        if(Validator.isEmpty(resultEntity1.getEntity())) {
            return resList;
        }
        resList = ( List<DataMap>)resultEntity1.getEntity();
        whereMap = new HashMap<>();
        whereMap.put("orderBy","dxInterfaceReg.sys_ename");
        ResultEntity resultEntity2 = IusPluginUtil.getInstance().select("list", "s_dxInterfaceReg", whereMap);
        if(Validator.isEmpty(resultEntity2.getEntity())) {
            return resList;
        }
        List<DataMap> list_inter = ( List<DataMap>)resultEntity2.getEntity();
        Map mapInter = new HashMap();
        //把注册的接口list融入到父级系统list内
        if (list_inter.size() > 0) {
            for (DataMap ds : resList) {
                String sysCname = String.valueOf(ds.get("sysCname"));
                String sysEname = String.valueOf(ds.get("sysEname"));
                String userOwner = String.valueOf(ds.get("userOwner"));
                ds.clear();
                List childList = new ArrayList<>();
                for (DataMap ds2 : list_inter) {
                    if (sysEname.equals(String.valueOf(ds2.get("sysEname")))) {
                        Map chMap = new HashMap();
                        chMap.put("name", String.valueOf(ds2.get("interfaceName")));
                        chMap.put("code", String.valueOf(ds2.get("interfaceCode")));
//                        chMap.put("value",interTotal);
                        childList.add(chMap);
                    }
                }
                ds.put("name",sysCname);
                ds.put("code",sysEname);
                ds.put("value",childList.size());
                ds.put("unit",userOwner);
                ds.put("children",childList);
            }
        }
        //按照每个系统子接口多少倒序排序
        Collections.sort(resList, new Comparator<DataMap>() {
            @Override
            public int compare(DataMap obj1, DataMap obj2) {
                Integer count1 = Integer.parseInt(StrUtil.doNull(String.valueOf(obj1.get("value")),"0"));
                Integer count2 = Integer.parseInt(StrUtil.doNull(String.valueOf(obj2.get("value")),"0"));
                //可以按User对象的其他属性排序，只要属性支持compareTo方法
                return count2.compareTo(count1);
            }
        });
        return resList;
    }

    /**
     * 统计查询-统计接口请求成功和失败
     */
    private void getStatistics2(Map<String, Object> map){
        String dateStr = StrUtil.doNull(String.valueOf(map.get("gte")), DateUtils.Now.fmt_yyyyMMdd())+ "T00:00:00";
        String datelte = StrUtil.doNull(String.valueOf(map.get("lte")), DateUtils.Now.fmt_yyyyMMdd())+ "T23:59:59";
        final String serverUrl = getSearchServerCtxByConfig();
        if (StrUtil.isNull(serverUrl)) {
            map.put(CustomMethodPlugin.resultMark,"统一查询(SEARCH-SERVER)服务已下线");
            return;
        }
        try {///"time_zone":"Asia/Shanghai",
            String esSuccess = "{\"size\":0,\"aggs\":{\"2\":{\"date_histogram\":{\"field\":\"indexDate\",\"interval\":\"1d\",\"min_doc_count\":1}}},\"stored_fields\":[\"*\"],\"docvalue_fields\":[\"indexDate\"],\"query\":{\"bool\":{\"must\":[{\"term\":{\"exeSys\":\"receive\"}},{\"term\":{\"infoType\":\"info\"}},{\"range\":{\"indexDate\":{\"gte\":\""+dateStr+"\",lte:\""+datelte+"\"}}}]}}}";
            String success = HttpService.sendHttp(serverUrl + "/statisticsByQuery/data-warn?indexType=log", "post", null, esSuccess, "json");
            JSONObject jsonSuccess = JSON.parseObject(success);
            String esFailure = "{\"size\":0,\"aggs\":{\"2\":{\"date_histogram\":{\"field\":\"indexDate\",\"interval\":\"1d\",\"min_doc_count\":1}}},\"stored_fields\":[\"*\"],\"docvalue_fields\":[\"indexDate\"],\"query\":{\"bool\":{\"must\":[{\"terms\":{\"exeSys\":[\"receive\",\"gateway\"]}},{\"terms\":{\"infoType\":[\"exception\",\"warning\"]}},{\"range\":{\"indexDate\":{\"gte\":\""+dateStr+"\",lte:\""+datelte+"\"}}}] }}}";//,"should":[{"wildcard":{"responseBody":"*500"}}]
            String failure = HttpService.sendHttp(serverUrl + "/statisticsByQuery/data-warn?indexType=log", "post", null, esFailure, "json");
            JSONObject jsonFailure = JSON.parseObject(failure);
            Map<String, Map<String,String>> data = new LinkedHashMap();
            if (jsonSuccess != null && jsonSuccess.containsKey("data")) {//成功的
                JSONArray jsons = jsonSuccess.getJSONArray("data");
                int count = jsons.size();
                for(int i=0;i<count;i++){
                    JSONObject obj = jsons.getJSONObject(i);
                    Map<String,String> sfMap = new HashMap();
                    String key = obj.getString("timeAsString").substring(0,10);
                    sfMap.put("success",obj.getString("count"));
                    sfMap.put("failure","0");
                    data.put(key,sfMap);
                }
            }
            if (jsonFailure != null && jsonFailure.containsKey("data")) {//错误的
                JSONArray jsons = jsonFailure.getJSONArray("data");
                int count = jsons.size();
                for(int i=0;i<count;i++){
                    JSONObject obj = jsons.getJSONObject(i);
                    String key = obj.getString("timeAsString").substring(0,10);
                    Map<String,String> sfMap = data.get(key);
                    if(sfMap==null){
                        sfMap = new HashMap();
                        sfMap.put("success","0");
                    }
                    sfMap.put("failure",obj.getString("count"));
                    data.put(key,sfMap);
                }
            }
            map.put(CustomMethodPlugin.resultMark, "T");
            map.put(CustomMethodPlugin.pluginInnerReturn, data);
        } catch (Exception e) {
            map.put(CustomMethodPlugin.resultMark, "数据统计查询出错，请重试");
            return;
        }
    }

    /**
     * 统计查询-请求次数折线图
     */
    private void getStatistics3(Map<String, Object> map) {
        String dateStr = StrUtil.doNull(String.valueOf(map.get("gte")), DateUtils.Now.fmt_yyyyMMdd())+ "T00:00:00";
        String datelte = StrUtil.doNull(String.valueOf(map.get("lte")), DateUtils.Now.fmt_yyyyMMdd())+ "T23:59:59";
        final String serverUrl = getSearchServerCtxByConfig();
        if (StrUtil.isNull(serverUrl)) {
            map.put(CustomMethodPlugin.resultMark,"统一查询(SEARCH-SERVER)服务已下线");
            return;
        }
        try {
            //String esSuccess = "{\"size\":0,\"aggs\":{\"2\":{\"date_histogram\":{\"field\":\"indexDate\",\"interval\":\"1d\",\"min_doc_count\":1}}},\"stored_fields\":[\"*\"],\"docvalue_fields\":[\"indexDate\"],\"query\":{\"bool\":{\"must\":[{\"term\":{\"exeSys\":\"receive\"}} ,{\"range\":{\"indexDate\":{\"gte\":\""+dateStr+"\",lte:\""+datelte+"\"}}}],\"should\":[{\"term\":{\"exeSys\":\"gateway\"}},{\"terms\":{\"infoType\":[\"warning\",\"exception\"]}}]}}}";//,{"term":{"infoType":"info"}}
            String esSuccess ="{\"size\":0,\"aggs\":{\"2\":{\"date_histogram\":{\"field\":\"indexDate\",\"interval\":\"1d\",\"min_doc_count\":1}}},\"stored_fields\":[\"*\"],\"docvalue_fields\":[\"indexDate\"],\"query\":{\"bool\":{\"should\":[{\"bool\":{\"must\":[{\"term\":{\"exeSys\":\"gateway\"}},{\"terms\":{\"infoType\":[\"warning\",\"exception\"]}},{\"range\":{\"indexDate\":{\"gte\":\""+dateStr+"\",lte:\""+datelte+"\"}}}]}},{\"bool\":{\"must\":[{\"term\":{\"exeSys\":\"receive\"}},{\"range\":{\"indexDate\":{\"gte\":\""+dateStr+"\",lte:\""+datelte+"\"}}}]}}]}}}";
            String success = HttpService.sendHttp(serverUrl + "/statisticsByQuery/data-warn?indexType=log", "post", null, esSuccess, "json");
            JSONObject jsonSuccess = JSON.parseObject(success);
            Map<String, String> data = new LinkedHashMap();
            if (jsonSuccess != null && jsonSuccess.containsKey("data")) {//成功的
                JSONArray jsons = jsonSuccess.getJSONArray("data");
                int count = jsons.size();
                for(int i=0;i<count;i++){
                    JSONObject obj = jsons.getJSONObject(i);
                    String key = obj.getString("timeAsString").substring(0,10);
                    data.put(key,obj.getString("count"));
                }
            }
            map.put(CustomMethodPlugin.resultMark, "T");
            map.put(CustomMethodPlugin.pluginInnerReturn, data);
        } catch (Exception e) {
            map.put(CustomMethodPlugin.resultMark, "数据统计查询出错，请重试");
            return;
        }
    }

    /**
     * 统计查询-统计接口调用次数top10榜
     */
    private void getStatistics4(Map<String, Object> map) {
        String searchRows = StrUtil.doNull(String.valueOf(map.get("rows")),"10");
        String dateStr = StrUtil.doNull(String.valueOf(map.get("gte")), DateUtils.Now.fmt_yyyyMMdd())+ "T00:00:00";
        String datelte = StrUtil.doNull(String.valueOf(map.get("lte")),"");
        if(StrUtil.isNotNull(datelte)){
            datelte =",\"lte\":\""+datelte+"T23:59:59\"";
        }
        final String serverUrl = getSearchServerCtxByConfig();
        if (StrUtil.isNull(serverUrl)) {
            map.put(CustomMethodPlugin.resultMark,"统一查询(SEARCH-SERVER)服务已下线");
            return;
        }
        try {//
            String esSql ="{\"size\":0,\"aggs\":{\"2\":{\"terms\":{\"field\":\"interfaceCode\",\"size\":"+searchRows+"}}},\"stored_fields\":[\"*\"],\"docvalue_fields\":[\"indexDate\"],\"query\":{\"bool\":{\"must\":[{\"term\":{\"exeSys\":\"receive\"}},{\"term\":{\"infoType\":\"info\"}},{\"range\":{\"indexDate\":{\"gte\":\""+dateStr+"\""+datelte+"}}}]}}}";
            String success = HttpService.sendHttp(serverUrl + "/statisticsByQuery/data-warn?indexType=log", "post", null, esSql, "json");
            JSONObject jsonSuccess = JSON.parseObject(success);
            if (jsonSuccess != null && jsonSuccess.containsKey("data")) {//成功的
                map.put(CustomMethodPlugin.resultMark, "数据获取成功");
                map.put(CustomMethodPlugin.pluginInnerReturn, jsonSuccess.get("data"));
                return ;
            }
            map.put(CustomMethodPlugin.resultMark,success);
        } catch (Exception e) {
            map.put(CustomMethodPlugin.resultMark, "数据统计查询出错，请重试");
            return;
        }
    }

    /**
     * 统计查询-统计服务使用方（接口被谁使用了)
     */
    private void getStatistics5(Map<String,Object> map){
        StringBuilder sb = new StringBuilder();
        sb.append("select DISTINCT r.interface_code,r.interface_name,r.sys_ename as source_sys_ename,r.user_owner as source_company,apply_sys_ename,apply_company from dx_interface_reg r,dx_sys_int_relation i");
        sb.append(" where r.interface_code=i.from_interface_code");
        String interfaceCode = String.valueOf(map.get("interfaceCode"));
        String sysEname = String.valueOf(map.get("sysEname"));
        if(StrUtil.isNotNull(interfaceCode)) {
            sb.append(" and r.interface_code='"+interfaceCode+"'");//接口编号
        }
        if(StrUtil.isNotNull(sysEname)) {
            sb.append(" and i.apply_sys_ename='"+sysEname+"'");//使用系统编号
        }
        List<DataMap<String>> list = (List)IusPluginUtil.getInstance().select(sb.toString(),0,0);
        if(StrUtil.isEmpty(list)){
            map.put(CustomMethodPlugin.resultMark,"暂无数据");
            return;
        }
        Map<String, List> data = new LinkedHashMap();
        int count = list.size();
        for(int i=0; i<count; i++){
            DataMap<String> info = list.get(i);
            List objs = data.get(info.get("sourceSysEname"));
            if(null == objs) {
                objs = new ArrayList();
            }
            objs.add(info);
            data.put(info.get("sourceSysEname"),objs);
        }
        map.put(CustomMethodPlugin.resultMark, "T");
        map.put(CustomMethodPlugin.pluginInnerReturn, data);
    }
    @Override
    public Object doInvoke(Map<String, Object> param) {
        return null;
    }
    @Override
    public Object afterInvoke(Map<String, Object> param) {
        return null;
    }
    /**
     * 规则校验统一入口
     * @param paramsVo
     */
    public void run(ParamsVo paramsVo) {
        beforeInvoke(paramsVo.getParams());
    }

    /**
     * 获取查询服务：根据系统版本模式：0/空=全版（默认 走hbase+searchServer），1=简版（不走hbase)
     * @return
     */
    private String getSearchServerCtxByConfig(){
        String sys_version_mode = StrUtil.doNull(CommonUtils.getConfigVal("sys_version_mode"), "0");
        String dataSendServer = "",dataServerName = "SEARCH-SERVER";
        if("0".equals(sys_version_mode)){
            dataSendServer = getRequestUrl("SEARCH-SERVER");
        }else{
            dataSendServer = getRequestUrl("RECEIVE-SERVER");
            dataServerName = "RECEIVE-SERVER";
        }
        log.info("config.sys_version_mode：["+sys_version_mode+"]["+dataServerName+"]->"+dataSendServer);
        return dataSendServer;
    }

    private String getRequestUrl(String serviceId){
        serviceId = StrUtil.doNull(serviceId,"RECEIVE-SERVER");
        DiscoveryManager discoveryClient = DiscoveryManager.getInstance();
        Application app = discoveryClient.getEurekaClient().getApplication(serviceId);
        if(app != null) {
            int dszie = app.getInstances().size();
            if (dszie > 0) {
                InstanceInfo instances = null;
                if(dszie > 1) {
                    Random rand = new Random();
                    instances = app.getInstances().get(rand.nextInt(dszie));
                } else {
                    instances = app.getInstances().get(0);
                }
                return instances.getHomePageUrl();
            }
        }
        return "";
    }
}